#pragma once

#include <angelscript.h>
#include <boost/filesystem/path.hpp>
#include <QtCore/QTextStream>
#include <logger/stream.hpp>

#include "exports.hpp"
#include "pointer.hpp"
#include "Module.hpp"




namespace Engine
{
	namespace Script
	{
		/**
		 * This is a helper class that eases the building process of modules.
		 *
		 * Once the build process is started, sections of code can be added from
		 * a range of sources, including a string in memory, files or arbitrary streams.
		 *
		 * Although a builder can be assigned or copied, the new Builder will not share the
		 * module with the old one: It will have no module at all.
		 */
		class ENGINE_SCRIPT_API Builder
		{
		public:

			Builder(logger::stream::ptr logger, pointer<asIScriptEngine> engine);
			Builder(const Builder& that);
			virtual ~Builder();



			/**
			 * Copies the given builder.
			 */
			Builder& operator=(const Builder& that);



			/**
			 * Starts building a new module with the given name.
			 * If a previous module has not been fully build, it is discarded.
			 * If there already is a module with that name a second one is created.
			 */
			void start(QString name);



			/**
			 * Adds the entire content of the given stream to the module.
			 */
			void add(QString name, QTextStream& stream);

			/**
			 * Adds the given uncompiled code to the module.
			 */
			void add(QString name, QString code);

			/**
			 * Adds the content from the given file to the module.
			 */
			void add(QString name, const boost::filesystem::path& file);



			/**
			 * Builds the entire module
			 *
			 * @returns the newly built script, baked into a module
			 * @throws when the module could not be build
			 */
			Module::ptr build();

		private:

			/**
			 * Runs the preprocessor on the given piece of code.
			 * Currently the preprocess only removes comments and hopefully
			 * it will never do more.
			 */
			QString preprocess(QTextStream& stream) const;

			/**
			 * Adds the given code the the list of code sections of the current module.
			 */
			void addSection(QString name, QString code);

		private:

			Module fromTextFile(const boost::filesystem::path& file);
			Module fromBinaryFile(const boost::filesystem::path& file);

		private:

			logger::stream::ptr        m_logger;
			pointer<asIScriptEngine>   m_engine;

			asIScriptModule*           m_module;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
